#include "messageshowarea.h"

MessageContentLabel::MessageContentLabel(MessageType messageType, const
        QString& text, const QString& fileId, const QByteArray& content, bool isLeft)
    : messageType(messageType), fileId(fileId), content(content),
      isLeft(isLeft)
{
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    QFont font;
    font.setFamily("微软雅⿊");
    font.setPixelSize(16);
    this->label = new QLabel(this);
    this->label->setText(text);
    this->label->setFont(font);
    this->label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    this->label->setWordWrap(true);
    this->label->setStyleSheet("QLabel { padding: 0 10px; line-height: 1.2;}");
}

void MessageContentLabel::paintEvent(QPaintEvent*)
{
    // 1. 拿到⽗元素的宽度
    QObject* object = this->parent();
    if (!object->isWidgetType())
    {
        return;
    }
    QWidget* parent = dynamic_cast<QWidget*>(object);
    // 宽度设置为⽗元素的 60%
    int width = parent->width() * 0.6;
    // 2. 计算⽂本的⾏数, 进⼀步得到⾼度
    QFontMetrics metrics(this->label->font());
    // 显⽰这些⽂本⼀共需要多宽
    int totalWidth = metrics.horizontalAdvance(this->label->text());
    int rows = (totalWidth / (width - 40)) + 1; // - 40 是给左右两侧留下⾜够的空隙
    if (totalWidth + 40 < width)
    {
        // ⽂本只有⼀⾏, 且不⾜⼀⾏, 就直接调整成更⼩的宽度
        width = totalWidth + 40;
    }
    int height = rows * (this->label->font().pixelSize() * 1.2) + 20; // + 20 是
    // + 20 是给上下留下点空⽩控件, 1.2 是考虑到⾏间距的问题
    // LOG() << "width: " << width << ", height: " << height << ", totalWidth:" << totalWidth << ", rows: " << rows;
    // 4. 绘制圆⻆矩形
    QPainter painter(this);
    // 设置抗锯⻮
    painter.setRenderHint(QPainter::Antialiasing);
    // 在这⾥画个⼩箭头 + 矩形
    QPainterPath path;
    if (isLeft)
    {
        painter.setPen(QPen(QColor(255, 255, 255), 1));
        painter.setBrush(QColor(255, 255, 255));
        path.addRoundedRect(10, 0, width, height, 10, 10);
        path.moveTo(10, 15);
        path.lineTo(0, 20);
        path.lineTo(10, 25);
        path.closeSubpath();
        painter.drawPath(path);
        // 5. 把 QLabel 移动到合适的位置
        this->label->setGeometry(10, 0, width, height);
    }
    else
    {
        painter.setPen(QPen(QColor(137, 217, 97), 1));
        painter.setBrush(QColor(137, 217, 97));
        // x 轴的起始位置. 此处⽤⾃⾝的 宽度 减去 label 的宽度, 再往左挪 10px
        int leftPos = this->width() - width - 10;
        int rightPos = this->width() - 10;
        path.addRoundedRect(leftPos, 0, width, height, 10, 10);
        path.moveTo(rightPos, 15);
        path.lineTo(rightPos + 10, 20);
        path.lineTo(rightPos, 25);
        path.closeSubpath();
        painter.drawPath(path);
        // 5. 把 QLabel 移动到合适的位置
        this->label->setGeometry(leftPos, 0, width, height);
        // 6. 设置⽗元素的⾼度, 确保⽗元素能够把当前整个⽂本都显⽰完整.
        // 50 这个数字是拍脑⻔拍的. 根据实际情况微调
        parent->setFixedHeight(height + 50);
    }
}

void MessageContentLabel::mousePressEvent(QMouseEvent *event)
{
    // TODO
}
void MessageContentLabel::contextMenuEvent(QContextMenuEvent *event)
{
    // TODO
}


MessageItem::MessageItem(bool isLeft) : isLeft(isLeft)
{

}

MessageItem* MessageItem::makeMessageItem(bool isLeft, const Message& message)
{
    // 1. 创建基本⻣架
    MessageItem* messageItem = new MessageItem(isLeft);
    QGridLayout* layout = new QGridLayout();
    layout->setContentsMargins(40, 10, 40, 0);
    layout->setHorizontalSpacing(10);
    layout->setVerticalSpacing(10);
    // layout->setColumnStretch(0, 0);
    // layout->setColumnStretch(1, 10);
    messageItem->setMinimumHeight(100);
    messageItem->setLayout(layout);

    // 2. 创建头像
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(40, 40);
    avatarBtn->setIconSize(QSize(40, 40));
    avatarBtn->setIcon(message.sender.avatar);
    if (isLeft)
    {
        layout->addWidget(avatarBtn, 0, 0, 2, 1, Qt::AlignTop | Qt::AlignLeft);
    }
    else
    {
        layout->addWidget(avatarBtn, 0, 1, 2, 1, Qt::AlignTop | Qt::AlignLeft);
    }


    // 3. 创建名字 和 时间
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(message.sender.nickname + " | " + message.time);
    nameLabel->setAlignment(Qt::AlignBottom);
    nameLabel->setStyleSheet("QLabel { font-size: 12px; color: rgb(178, 178,178); }");
    if (isLeft)
    {
        layout->addWidget(nameLabel, 0, 1);
    }
    else
    {
        layout->addWidget(nameLabel, 0, 0, Qt::AlignRight);
    }

    // 4. 创建消息体
    QWidget* contentWidget = nullptr;
    switch (message.messageType)
    {
        case TEXT_TYPE:
            contentWidget = makeTextMessageItem(message.content, isLeft);
            break;
        case IMAGE_TYPE:
            contentWidget = makeImageMessageItem(message.fileId, message.content,
                                                 isLeft);
            break;
        case FILE_TYPE:
            contentWidget = makeFileMessageItem(message.fileId, message.content,
                                                isLeft, message.fileName);
            break;
        case SPEECH_TYPE:
            contentWidget = makeSoundMessageItem(message.fileId, message.content,
                                                 isLeft);
            break;
        default:
            LOG() << "error messageType! messageType = " << message.messageType;
    }
    if (isLeft)
    {
        layout->addWidget(contentWidget, 1, 1);
    }
    else
    {
        layout->addWidget(contentWidget, 1, 0);
    }

    // 5. 关联信号槽
    // 5.1 点击头像, 弹出窗⼝显⽰⽤⼾信息.
    // connect(avatarBtn, &QPushButton::clicked, messageItem, [=]() {
    //     UserInfoWidget* userInfoWidget = new UserInfoWidget(message);
    //     userInfoWidget->show();
    // });

    // 5.2 ⽤⼾修改了昵称, 则修改昵称内容. TODO
    return messageItem;
}

QWidget* MessageItem::makeTextMessageItem(const QByteArray &content, bool isLeft)
{
    // ⽂本消息不需要 fileId
    MessageContentLabel* item = new MessageContentLabel(TEXT_TYPE, QString(content), "", content, isLeft);
    return item;
}

QWidget* MessageItem::makeImageMessageItem(const QString& fileId, const
        QByteArray &content, bool isLeft)
{
    MessageImageLabel* item = new MessageImageLabel(fileId, content, isLeft);
    return item;
}
QWidget* MessageItem::makeFileMessageItem(const QString& fileId, const
        QByteArray &content, bool isLeft, const QString& fileName)
{
    MessageContentLabel* item = new MessageContentLabel(FILE_TYPE, "[⽂件] " +
        fileName, fileId, content, isLeft);
    return item;
}
QWidget* MessageItem::makeSoundMessageItem(const QString& fileId, const
        QByteArray &content, bool isLeft)
{
    MessageContentLabel* item = new MessageContentLabel(SPEECH_TYPE, "[语⾳]",
        fileId, content, isLeft);
    return item;
}

MessageShowArea::MessageShowArea(QWidget *parent)
    : QScrollArea(parent)
{
    // 1. 初始化基础属性
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    // ⼀定要添加这个设置, 否则⽆法正确显⽰.
    this->setWidgetResizable(true);
    // 隐藏⽔平滚动条. 把垂直滚动条设置的细⼀些
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width:2px; background-color: rgb(240, 240, 240); } QScrollBar::handle:vertical{background-color: rgb(46, 46, 46);}");
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal {height: 0px;}");
    this->setStyleSheet("QScrollArea { border: none;}");

    // 2. 创建核⼼ Widget
    // 此处设置个最⼩宽度. ⽽不设置固定宽度
    container = new QWidget();
    this->setWidget(container);

    // 3. 给核⼼ Widget 添加布局
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
    container->setLayout(layout);
}

void MessageShowArea::addMessage(bool isLeft, const Message& message)
{
    MessageItem* messageItem = MessageItem::makeMessageItem(isLeft, message);
    container->layout()->addWidget(messageItem);
}

void MessageShowArea::clear()
{
    QLayout* layout = container->layout();
    // 从后往前遍历. 否则删除前⾯的元素会影响后⾯元素的下标
    for (int i = layout->count() - 1; i >= 0; i--)
    {
        QLayoutItem* item = layout->takeAt(i);
        if (item->widget())
        {
            delete item->widget();
        }
        delete item;
    }

}

// 如果直接进⾏滚动到最后, 可能得不到正确结果. 因为添加控件到布局管理器, 触发界⾯⼤⼩resize 是⼀个异步过程.
// 此处耍个花招, 通过定时器, 延时 500ms 之后才真正进⾏滚动.
void MessageShowArea::scrollToEndLater()
{
    LOG() << "scrollToEndLater";
    QTimer* timer = new QTimer();
    connect(timer, &QTimer::timeout, this, [ = ]()
    {
        // 执⾏滚动操作
        int maxValue = this->verticalScrollBar()->maximum();
        this->verticalScrollBar()->setValue(maxValue);
        // 销毁定时器
        timer->stop();
        timer->deleteLater();
    });
    timer->start(500);
}


MessageImageLabel::MessageImageLabel(const QString& fileId, const QByteArray &conten, bool isLeft)
{

}

MessageEditArea::MessageEditArea(QWidget *owner)
    : owner(owner)
{
    // 1. 设置基础属性
    this->setFixedHeight(200);
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    // 2. 创建纵向布局管理器
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setContentsMargins(10, 0, 10, 10);
    layout->setSpacing(0);
    layout->setAlignment(Qt::AlignTop);
    this->setLayout(layout);
    // 3. 创建⼯具按钮容器 Widget
    QWidget* toolsContainer = new QWidget();
    toolsContainer->setFixedHeight(35);
    layout->addWidget(toolsContainer);
    // 3.1 创建⼯具按钮的布局管理器.
    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(10, 0, 0, 0);
    hlayout->setSpacing(0);
    hlayout->setAlignment(Qt::AlignLeft);
    toolsContainer->setLayout(hlayout);
    // 3.2 创建⼯具按钮
    QString buttonStyle = "QPushButton { background-color: rgb(245, 245, 245);border: none; } QPushButton:pressed { background-color: rgb(255, 255, 255);}";
    QSize buttonSize(35, 35);
    QSize iconSize(25, 25);

    sendImageBtn = new QPushButton();
    sendImageBtn->setFixedSize(buttonSize);
    sendImageBtn->setIconSize(iconSize);
    sendImageBtn->setIcon(QIcon("://resource/image/Image.png"));
    sendImageBtn->setStyleSheet(buttonStyle);
    hlayout->addWidget(sendImageBtn);
    sendFileBtn = new QPushButton();
    sendFileBtn->setFixedSize(buttonSize);
    sendFileBtn->setIconSize(iconSize);
    sendFileBtn->setIcon(QIcon("://resource/image/file.png"));
    sendFileBtn->setStyleSheet(buttonStyle);
    hlayout->addWidget(sendFileBtn);
    sendSoundBtn = new QPushButton();
    sendSoundBtn->setFixedSize(buttonSize);
    sendSoundBtn->setIconSize(iconSize);
    sendSoundBtn->setIcon(QIcon("://resource/image/sound.png"));
    sendSoundBtn->setStyleSheet(buttonStyle);
    hlayout->addWidget(sendSoundBtn);
    showHistoryBtn = new QPushButton();
    showHistoryBtn->setFixedSize(buttonSize);
    showHistoryBtn->setIconSize(iconSize);
    showHistoryBtn->setIcon(QIcon("://resource/image/History.png"));
    showHistoryBtn->setStyleSheet(buttonStyle);
    hlayout->addWidget(showHistoryBtn);

    // 4. 创建编辑框
    textEdit = new QPlainTextEdit();
    textEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    textEdit->setStyleSheet("QPlainTextEdit { border: none; background-color:transparent; font-size: 14px; padding: 10px; } ");
    textEdit->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width:2px; background-color: rgb(46, 46, 46); }");
    layout->addWidget(textEdit);
    // 5. 创建⼀个提⽰信息 label, 默认状态为隐藏
    tipLabel = new QLabel();
    tipLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    tipLabel->setText("录⾳中...");
    tipLabel->setAlignment(Qt::AlignCenter);
    tipLabel->setFont(QFont("微软雅⿊", 24, 600));
    layout->addWidget(tipLabel);
    tipLabel->hide();

    // 6. 创建发送按钮
    sendBtn = new QPushButton();
    sendBtn->setText("发送");
    sendBtn->setFixedSize(120, 40);
    QString style = "QPushButton { font-size: 16px; color: rgb(7, 193, 96);border: none; background-color: rgb(233, 233, 233); border-radius: 10px; }";
    style += "QPushButton:hover { background-color: rgb(210, 210, 210); } ";
    style += "QPushButton:pressed { background-color: rgb(198, 198, 198);} ";
    sendBtn->setStyleSheet(style);
    layout->addWidget(sendBtn, 0, Qt::AlignRight | Qt::AlignVCenter);
}
